package com.audi.box.controller;

import java.util.ArrayList;
import android.content.Context;

import com.audi.box.adapter.SQLiteAsusHelperDevice;
import com.audi.box.server.message.ActionMessage;
import com.audi.box.service.DeviceService;
import com.audi.box.service.DeviceServiceImp;
import com.audi.dto.DeviceItem;
import com.audi.dto.PlaceItem;

/**
 * @author CuongPH7
 */
public class DeviceController implements IController {
    private static Object dclObj = new Object();
    private DeviceService deviceService;
    private HistoryController historyController;
    private PlaceController placeController;
    private static DeviceController deviceController = null;
    
    /**
     * Class constructor specifying Context to create
     * 
     * @param context
     *            android.content.Context
     * @throws Exception
     *             if (can not create DeviceServiceImp
     */
    public DeviceController(final Context context) throws Exception {
        
        deviceService = new DeviceServiceImp(
                new SQLiteAsusHelperDevice(context));
        
        historyController = HistoryController.getInstance(context);
        placeController = PlaceController.getInstance(context);
    }
    
    /**
     * Class constructor specifying DeviceService to create.
     * 
     * @param deviceService
     *            DeviceService
     * @see DeviceService
     */
    public DeviceController(DeviceService deviceService) {
        this.deviceService = deviceService;
    }
    
    /**
     * Make a Singleton Instance.
     * 
     * @param context
     *            Android.content.Context
     * @return an Instance DeviceController
     * @throws Exception
     */
    public static DeviceController getInstance(final Context context)
            throws Exception {
        if (deviceController == null) {
            synchronized (dclObj) {
                if (deviceController == null) {
                    deviceController = new DeviceController(context);
                }
            }
        }
        
        return deviceController;
    }
    
    /**
     * Inject DeviceService.
     * 
     * @param deviceService
     *            DeviceService
     * @see DeviceService
     */
    public void setDeviceService(DeviceService deviceService) {
        this.deviceService = deviceService;
    }
    
    /**
     * Inject HistoryController
     * 
     * @param historyController
     *            HistoryController
     * @see HistoryController
     */
    public void setHistoryController(HistoryController historyController) {
        this.historyController = historyController;
    }
    
    /**
     * Add new device item.
     * 
     * @param deviceName
     *            Device Name
     * @param deviceIcon
     *            Device Icon
     * @param deviceStatus
     *            Device Status
     * @param deviceType
     *            Device Type
     * @param deviceStatusValue
     *            Device Status Value
     * @param deviceCode
     *            Device Code
     * @param deviceBoxId
     *            Box Id
     * @param devicePlaceId
     *            Place Id
     * @param userId
     *            User id
     * @return Device Id if (successful, 0 if (device is exist
     * @throws Exception
     *             if (device is null or device information missing)
     */
    public int addDevice(String deviceName, String deviceIcon,
            int deviceStatus, int deviceType, int deviceStatusValue,
            String deviceCode, int deviceBoxId, int devicePlaceId, int userId) {
        DeviceItem device = new DeviceItem();
        
        device.setDeviceName(deviceName);
        device.setDeviceIcon(deviceIcon);
        device.setDeviceStatus(deviceStatus);
        device.setDeviceType(deviceType);
        device.setStatusValue(deviceStatusValue);
        device.setDeviceCode(deviceCode);
        device.setDeviceBoxId(deviceBoxId);
        device.setDevicePlaceId(devicePlaceId);
        device.setUserId(userId);
        
        return addDevice(device);
    }
    
    /**
     * Add new device item.
     * 
     * @param device
     *            DeviceItem
     * @return Device Id if (successful, 0 if (device is exist
     * @throws Exception
     *             if (device is null or device information missing)
     */
    public int addDevice(DeviceItem device) {
        int result = 0;
        
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDeviceName() == null || device.getDeviceName().equals("")
                || device.getDeviceCode() == null
                || device.getDeviceCode().equals("")
                || device.getDevicePlaceId() == null
                || device.getDevicePlaceId() == 0 || device.getUserId() == null
                || device.getUserId() == 0) {
            throw new NullPointerException("Device Information is missing");
        } else if (device.getDeviceId() != null && device.getDeviceId() != 0
                && isExist(device)) {
            return 0;
        } else {
            result = deviceService.addDevice(device);
            
            // UPDATE HISTORY
            if (result > 0) {
                DeviceItem newDevice = deviceService.getDevice(result);
                historyController.addHistoryDevice(ActionMessage.ADD_DEVICE,
                        newDevice, newDevice, 1, "CuongPH7 Hard Code");
            }
            return result;
        }
    }
    
    /**
     * Add new HARDWARE device, used by sensor controller
     * 
     * @param deviceCode
     *            Sensor unique code
     * @param deviceGroupdType
     *            Sensor group type (ONOFF SENSOR / WARNING SENSOR / ALARM
     *            SENSOR)
     * @return Device Id if (successful, 0 if (device is exist
     * @throws Exception
     *             if (device is null or device information missing
     */
    public int addNewDevice(String deviceCode, int deviceGroupdType) {
        
        DeviceItem device = new DeviceItem();
        device.setDeviceCode(deviceCode);
        device.setDeviceType(deviceGroupdType);
        
        return addNewDevice(device);
        
    }
    
    /**
     * Add new HARDWARE device, used by sensor controller
     * 
     * @param device
     *            DeviceItem
     * @see DeviceItem
     * @return Device Id if (successful 0 if (device is exist
     * @throws Exception
     *             if (device is null or device information missing
     */
    public int addNewDevice(DeviceItem device) {
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDeviceCode() == null || device.getDeviceCode().equals("")
                || device.getDeviceType() == 0) {
            throw new NullPointerException("Device Information is missing");
        } else if (deviceService.isExistByDeviceCode(device)) {
            return 0;
        } else {
            return deviceService.addNewDevice(device);
        }
    }
    
    /**
     * Delete a Device
     * 
     * @param device
     *            DeviceItem
     * @return 1 if (successful, 0 if (device is not exist
     */
    public int deleteDevice(DeviceItem device) {
        int result = 0;
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDeviceId() == null || device.getDeviceId() == 0) {
            throw new NullPointerException("Device Information is missing");
        }
        
        // UPDATE HISTORY: GET OLD DEVICE INFORMATION
        DeviceItem oldDevice = deviceService.getDevice(device.getDeviceId());
        
        result = deviceService.deleteDevice(device);
        
        // UPDATE HISTORY
        if (result > 0) {
            historyController.addHistoryDevice(ActionMessage.DELETE_DEVICE
                    , oldDevice, oldDevice, 1, "CuongPH7 Hard Code");
        }
        
        return result;
    }
    
    /**
     * Get Device List By Group Type
     * 
     * @param deviceGroupType
     *            Device Group Type
     * @return An ArrayList Device
     */
    public ArrayList<DeviceItem> getDeviceList(int deviceGroupType) {
        return deviceService.getListDevice(deviceGroupType);
    }
    
    /**
     * Get All Device List
     * 
     * @return An ArrayList Device
     */
    public ArrayList<DeviceItem> getDeviceList() {
        return deviceService.getListDevice();
    }
    
    /**
     * Get Device List By User Id
     * 
     * @param userId
     *            User Id
     * @return An ArrayList Device
     */
    public ArrayList<DeviceItem> getDeviceByUserId(int userId) {
        return deviceService.getListDeviceByUserId(userId);
    }
    
    /**
     * Get Device List By Place Id
     * 
     * @param placeId
     *            Place Id
     * @return An ArrayList Device
     */
    public ArrayList<DeviceItem> getDeviceByPlaceId(int placeId) {
        return deviceService.getListDeviceByPlaceId(placeId);
    }
    
    /**
     * Get Device Item information
     * 
     * @param deviceId
     *            Device Id
     * @return DeviceItem
     */
    public DeviceItem getDeviceById(int deviceId) {
        return deviceService.getDevice(deviceId);
    }
    
    /**
     * Get New HARDWARE Device List
     * 
     * @return An ArrayList Device
     */
    public ArrayList<DeviceItem> getNewDevice() {
        return deviceService.getNewDevice();
    }
    
    /**
     * Check Device exist
     * 
     * @return <code>true</code> if Device exist <code>false</code> if Device is
     *         not Exist
     */
    public boolean isExist(DeviceItem device) {
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        return deviceService.isExist(device);
    }
    
    /**
     * Check Device's Name exist
     * 
     * @return <code>true</code> if Device exist <code>false</code> if Device is
     *         not Exist
     */
    public boolean isExistByName(DeviceItem device) {
        
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        return deviceService.isExistByDeviceName(device);
    }
    
    /**
     * Update Device Item
     * <p>
     * Add 06/09
     * 
     * @param device
     *            DeviceItem
     * @return 1 if successful, 0 if device is not exist
     */
    public int updateDevice(DeviceItem device) {
        int result = 0;
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDeviceName() != null && device.getDeviceName().equals("")) {
            throw new NullPointerException("Device Information is missing");
        }
        
        if (!deviceService.isExist(device)) {
            return 0;
        }
        
        /*
         * // UPDATE HISTORY: GET OLD DEVICE INFORMATION DeviceItem oldDevice =
         * deviceService.getDevice(device.getDeviceId());
         */
        
        result = deviceService.updateDevice(device);
        
        /*
         * // UPDATE HISTORY if (result > 0) {
         * historyController.addHistoryDevice(ActionMessage.UPDATE_DEVICE,
         * oldDevice, device); }
         */
        
        return result;
    }
    
    /**
     * Rename Device Item
     * <p>
     * Add 06/09
     * 
     * @param device
     *            DeviceItem
     * @return 1 if successful, 0 if device is not exist or Device Name Exist
     */
    public int renameDevice(DeviceItem device) {
        int result = 0;
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDeviceName() == null || device.getDeviceName().equals("")) {
            throw new NullPointerException("Device Information is missing");
        }
        // else if (deviceService.isExistByDeviceName(device)) {
        // return 0;
        // }
        
        /*
         * // UPDATE HISTORY: GET OLD DEVICE INFORMATION DeviceItem oldDevice =
         * deviceService.getDevice(device.getDeviceId());
         */
        
        result = updateDevice(device);
        
        /*
         * // UPDATE HISTORY if (result > 0) {
         * historyController.addHistoryDevice(ActionMessage.RENAME_DEVICE,
         * oldDevice, device); }
         */
        
        return result;
    }
    
    /**
     * Change Device's Place (move a device from a place to another place)
     * <p>
     * Add 06/09
     * 
     * @param device
     *            DeviceItem
     * @return 1 if successful, 0 if device is not exist or Device Name Exist
     */
    public int changePlace(DeviceItem device) {
        int result = 0;
        
        if (device == null) {
            throw new NullPointerException("Device is Null");
        }
        
        if (device.getDevicePlaceId() == null || device.getDevicePlaceId() == 0) {
            throw new NullPointerException("Device Information is missing");
        }
        
        // UPDATE HISTORY: GET OLD DEVICE INFORMATION
        DeviceItem oldDevice = deviceService.getDevice(device.getDeviceId());
        
        result = updateDevice(device);
        
        // UPDATE HISTORY
        if (result > 0) {
            historyController.addHistoryDevice(ActionMessage.CHANGE_PLACE_OF_DEVICE,
                    oldDevice, device, 1, "CuongPH7 Hard Code");
            
        }
        return result;
    }
    
    /**
     * Change Device List's Place (move a device list from a place to another
     * place).
     * <p>
     * Add 06/09
     * 
     * @param lstDevice
     *            ArrayList<DeviceItem>
     * @param place
     *            PlaceItem
     * @return number rows effected if successful, 0 if fail
     */
    public int changePlaceforDeviceList(ArrayList<DeviceItem> lstDevice,
            PlaceItem place) {
        int result = 0;
        
        if ((lstDevice == null) || (lstDevice.size() == 0) || (place == null)
                || (place.getPlaceId() == null)) {
            throw new NullPointerException(
                    "DeviceItem List or PlaceItem is Null");
        }
        
        PlaceItem newPlace = placeController.getPlace(place.getPlaceId());
        
        if ((newPlace.getPlaceId() == null)
                || (newPlace.getPlaceId() == 0)) {
            throw new NullPointerException(
                    "Place does not exist");
        }
        
        // UPDATE HISTORY: GET OLD DEVICE INFORMATION
        ArrayList<DeviceItem> lstOldDevice = lstDevice;
        int[] arrDeviceId = new int[lstOldDevice.size()];
        for (int i = 0; i < lstOldDevice.size(); i++) {
            if ((lstOldDevice.get(i)).getDeviceId() != null
                    && (lstOldDevice.get(i)).getDeviceId() != 0) {
                
                arrDeviceId[i] = (lstOldDevice.get(i)).getDeviceId();
                
            }
        }
        lstOldDevice = deviceService.getDevice(arrDeviceId);
        
        result = deviceService.changePlaceforDeviceItemList(lstDevice, place);
        
        // UPDATE HISTORY
        if (result > 0) {
            for (DeviceItem oldDevice : lstOldDevice) {
                DeviceItem newDevice = oldDevice;
                newDevice.setDevicePlaceId(newPlace.getPlaceId());
                newDevice.setDevicePlace(newPlace.getPlaceName());
                historyController.addHistoryDevice(ActionMessage.CHANGE_PLACE_OF_DEVICE,
                        oldDevice, newDevice, 1, "CuongPH7 Hard Code", lstOldDevice.size());
            }
        }
        
        return result;
    }
    
    /**
     * Change Favorite for a Device Item List.
     * 
     * @param lstDevice
     *            Arraylist<DeviceItem>
     * @return 1 if all device are changed successful 0 if any device changed
     *         fail
     */
    public int changeFavoriteforDeviceList(ArrayList<DeviceItem> lstDevice) {
        int result = 0;
        
        if ((lstDevice == null) || (lstDevice.size() == 0)) {
            throw new NullPointerException("Device List is Null or empty");
        }
        
        /*
         * // UPDATE HISTORY: GET OLD DEVICE INFORMATION ArrayList<DeviceItem>
         * lstOldDevice = lstDevice; int[] arrDeviceId = new
         * int[lstOldDevice.size()]; for (int i = 0; i < lstOldDevice.size();
         * i++) { if ((lstOldDevice.get(i)).getDeviceId() != null &&
         * (lstOldDevice.get(i)).getDeviceId() != 0) {
         * 
         * arrDeviceId[i] = (lstOldDevice.get(i)).getDeviceId();
         * 
         * } } lstOldDevice = deviceService.getDevice(arrDeviceId);
         */
        
        result = deviceService.changeFavoriteForDeviceList(lstDevice);
        
        /*
         * // UPDATE HISTORY if (result > 0) { // SORT DEVICE ITEM LIST BY
         * DEVICE ID (ASC); Collections.sort(lstOldDevice,
         * ItemComparator.ComparatorDeviceById); Collections.sort(lstDevice,
         * ItemComparator.ComparatorDeviceById);
         * 
         * for (int i = 0; i < lstOldDevice.size(); i++) {
         * historyController.addHistoryDevice
         * (ActionMessage.UPDATE_FAVORITE_DEVICE, lstOldDevice.get(0),
         * lstDevice.get(0)); } }
         */
        
        return result;
    }
    
    /**
     * Change Device List's Place (move a device list from a place to another
     * place).
     * <p>
     * Add 06/09
     * 
     * @param lstDevice
     *            ArrayList<DeviceItem>
     * @param place
     *            PlaceItem
     * @return number rows effected if successful, 0 if fail
     */
    public ArrayList<DeviceItem> getListDeviceFavorite() {
        return deviceService.getListDeviceFavorite();
    }
    
}
